#ifndef _GENERIC_HLS
#define _GENERIC_HLS

#include <stdint.h>
#include <pthread.h>
#include <time.h>
#include <curl/curl.h>
#include "utils.h"

#define AES128_KEY_SIZE			16
#define MAX_STR_LEN				4906
#define	HLS_MAX_STREAMS			12
#define HLS_MAX_IV_COUNT		100000

#define HLS_START_MIN			0xFFFFFFFFFFFFFFF0
#define HLS_START_MID			0xFFFFFFFFFFFFFFF1
#define HLS_START_MAX			0xFFFFFFFFFFFFFFF2

#define HLS_KEY_TYPE_NONE		0x00
#define HLS_KEY_TYPE_AES128		0x01
#define HLS_KEY_TYPE_UNKNOWN	0x02

#define HLS_STATE_END		1
#define HLS_STATE_LIVE		2
#define HLS_STATE_BAD		3


#define HLS_PROXY_TYPE_HTTP		0x01
#define HLS_PROXY_TYPE_SOCKS	0x02

#define HLS_SEGMENT_LIVE_MINUS	6

/*
static const char *HLS_KEY_TYPE[3] =
{
	"None",
	"AES-128",
	"Unknown",
};

static const char *HLS_STATE_STRINGS[4] =
{
	"",
	"End of Playlist",
	"Still Live",
	"Invalid Playlist"
};
*/
struct hls_fetch_options
{
	uint8_t throw_away;
	CURL *handle;
	char *errbuf;
	char *user_agent;
	uint8_t proxy_type;
	char *proxy;
	int connect_timeout;
	int timeout;
	int buffer_size;
	int dns_cache_timeout;
	int fail_on_error;
	char *cookie_file;
	char *cookie_jar;

};
typedef struct hls_fetch_options HLS_FETCH_OPTIONS;


struct hls_key
{
	void *extra_data;
	uint8_t type;
	char *uri;
	uint8_t key[AES128_KEY_SIZE];
	uint8_t iv[AES128_KEY_SIZE];
	struct hls_stream_url *stream;
//	struct hls_segment *parent;
};
typedef struct hls_key HLS_KEY;

struct hls_segment
{
	int32_t			stream_index;
	HLS_KEY 		*key;
	char 			*url;
	char 			*title;
	double 			duration;		// duration of segment
	uint64_t		process_time; 	// Speed
	uint64_t		index;			// index number
	double			timecode;		// stream time, relative to HLS stream time
//	uint64_t		pts;			// timecode of TS segment, in 90khz clock
	UTILS_DATAPAIR_STRUCT data;

	struct hls_segment *prev;
	struct hls_segment *next;
	struct hls_stream_url *parent;
};
typedef struct hls_segment HLS_SEGMENT;

struct hls_stream_url
{
	uint32_t		index;
	int8_t 			state;
	uint8_t 		valid;
	uint32_t 		program_id;
	uint64_t 		bandwidth;
	uint64_t 		last_update_time;
	char 			*url;
	char 			*base_url;
	uint64_t		start_time;
	double 			ext_x_media_seq;
	double 			ext_x_version;
	double 			ext_x_target_duration;
	uint64_t	 	ext_x_data_time;
	uint64_t 		ext_x_key;


	uint64_t	iv_keys_count;
	HLS_KEY		*active_iv_key;
	HLS_KEY 	iv_keys[HLS_MAX_IV_COUNT];

	UTILS_DATAPAIR_STRUCT playlist_mem;
	TEXTFILE_IN_MEMORY *memfile;

	uint64_t segment_count;
	uint32_t playlist_position;
	HLS_SEGMENT *active_segment;
	HLS_SEGMENT *first_segment;
	HLS_SEGMENT *curent_segment;

	struct hls_master_url *parent;
};
typedef struct hls_stream_url HLS_STREAM_URL;



struct hls_master_url
{
	void 						*extra_data;
	UTILS_DATAPAIR_STRUCT 		list_mem;
	HLS_FETCH_OPTIONS 			playlist_opts;
	HLS_FETCH_OPTIONS 			segment_opts;
	uint8_t 					*decrypt_mem;
	int 						decrypt_mem_ret;
	int 						decrypt_mem_size;

	char 						*fetch_proxy;
	char 						*master_url;
	char 						*base_url;
	char 						*url_params;
	uint32_t 					stream_index;
	uint64_t 					starting_bandwidth;
	uint64_t 					min_bandwidth;
	uint64_t 					max_bandwidth;
	uint8_t 					adaptive;

	uint64_t 					segment_fetch_index;
	uint32_t 					stream_count;
	HLS_STREAM_URL 				*active_stream;
	HLS_STREAM_URL 				streams[HLS_MAX_STREAMS];

	char 						curl_errbuf[CURL_ERROR_SIZE];

	uint8_t (*cb_process_ext_x_key)(HLS_STREAM_URL *);
	uint8_t (*cb_post_decrypt)(HLS_SEGMENT *);
	uint8_t (*cb_post_fetch)(HLS_SEGMENT *);
};
typedef struct hls_master_url HLS_MASTER_URL;



UTILS_DATAPAIR_STRUCT * hls_curl_get(char *, HLS_FETCH_OPTIONS *);
UTILS_DATAPAIR_STRUCT * hls_curl_post(char *, char *, HLS_FETCH_OPTIONS *);

void hls_curl_set_opts(CURL *, HLS_FETCH_OPTIONS *);

HLS_MASTER_URL * hls_init(char *);
void hls_destroy(HLS_MASTER_URL *);
void hls_print_stream_info(HLS_MASTER_URL *);
int hls_update_stream_playlist(HLS_MASTER_URL *);

int hls_set_bitrate(HLS_MASTER_URL *, uint64_t);
int hls_switch_bitrate_up(HLS_MASTER_URL *, uint64_t);
int hls_switch_bitrate_down(HLS_MASTER_URL *, uint64_t);

HLS_SEGMENT * hls_stream_fetch_decrypt(HLS_STREAM_URL *);


HLS_SEGMENT * hls_set_segment_time(HLS_STREAM_URL *, double);
HLS_SEGMENT * hls_set_segment_index(HLS_STREAM_URL *, uint64_t);
HLS_SEGMENT * hls_set_segment_live(HLS_STREAM_URL *);

uint64_t hls_get_stream_start_datetime(HLS_STREAM_URL *);
uint8_t hls_get_stream_state(HLS_STREAM_URL *);
uint64_t hls_get_stream_segment_count(HLS_STREAM_URL *);
void hls_set_adaptive(HLS_MASTER_URL *, uint8_t);
void hls_set_max_bitrate(HLS_MASTER_URL *, uint64_t);
void hls_set_min_bitrate(HLS_MASTER_URL *, uint64_t);


#endif

